package com.ninong.ker.gateway.filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.ninong.ker.gateway.auth.CmdResponse;
import com.ninong.ker.gateway.auth.SecurityAdmin;
import com.ninong.ker.gateway.auth.Signutil;
import com.ninong.ker.gateway.conf.FilterProperties;

import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;

import javax.validation.constraints.Pattern;

/**
 * 网关鉴权
 * 
 * @author cmd
 *
 */
@Slf4j
@Component
@RefreshScope
public class AuthFilter implements GlobalFilter {

	@Autowired
	private SecurityAdmin securityAdmin;

	@Autowired
	private FilterProperties filterProperties;

	@Override
	public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
		String requestRri = exchange.getRequest().getURI().getPath();
		log.info("url:{}", requestRri);
		// 跳过不需要验证的路径
		if (isAllowPath(requestRri)) {
			return chain.filter(exchange);
		}
		if (securityAdmin.getAuth()) {
			String invokeTime = exchange.getRequest().getHeaders().getFirst("invokeTime");
			String sign = exchange.getRequest().getHeaders().getFirst("sign");
			log.info("getHeaderParamenters===>time:{}, sign:{}", invokeTime, sign);
			if (!StringUtils.isEmpty(invokeTime) && !StringUtils.isEmpty(sign)) {
				if (!Signutil.interfaceSecurityAuth(Long.valueOf(invokeTime), sign,requestRri)) {
					return getVoidMono(exchange);
				}
			}else {
				return getVoidMono(exchange);
			}
		}
		String token = securityAdmin.getToken(exchange.getRequest());
		if (StringUtils.isEmpty(token) || !securityAdmin.validateToken(token)) {
			log.info("token is empty...");
			// 设置status和body
			return Mono.defer(() -> {
				exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);// 设置status
				final ServerHttpResponse response = exchange.getResponse();
				CmdResponse jsonObject = new CmdResponse();
				jsonObject.setCode(401);
				jsonObject.setMessage("鉴权失败");
				DataBuffer buffer = null;
				final SerializerFeature[] features = { SerializerFeature.DisableCircularReferenceDetect,
						SerializerFeature.WriteDateUseDateFormat };
				buffer = exchange.getResponse().bufferFactory().wrap(JSONObject.toJSONBytes(jsonObject, features));
				response.getHeaders().set("Content-Type", "application/json;charset=UTF-8");
				// 设置body
				return response.writeWith(Mono.just(buffer));
			});
		}
		return chain.filter(exchange);
	}

	private Mono<Void> getVoidMono(ServerWebExchange exchange) {
		log.info("接口有效期失效。。。。");
		// 设置status
		exchange.getResponse().setStatusCode(HttpStatus.REQUEST_TIMEOUT);
		final ServerHttpResponse response = exchange.getResponse();
		CmdResponse jsonObject = new CmdResponse();
		jsonObject.setCode(HttpStatus.REQUEST_TIMEOUT.value());
		jsonObject.setMessage("接口失效");
		DataBuffer buffer = null;
		final SerializerFeature[] features = {SerializerFeature.DisableCircularReferenceDetect,
				SerializerFeature.WriteDateUseDateFormat};
		buffer = exchange.getResponse().bufferFactory().wrap(JSONObject.toJSONBytes(jsonObject, features));
		response.getHeaders().set("Content-Type", "application/json;charset=UTF-8");
		// 设置body
		return response.writeWith(Mono.just(buffer));
	}

	private boolean isAllowPath(String path) {
		// 遍历白名单
		for (String allowPath : filterProperties.getAllowPaths()) {
			// 判断是否允许
			if (path.startsWith(allowPath)) {
				return true;
			}
		}
		return false;
	}
}